﻿using AutoUpdateTool.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace AutoUpdateTool
{
    internal delegate void MAction();
    internal class Common
    {
        /// <summary>
        /// 默认配置清单文件名
        /// </summary>
        public static readonly string ManifestName = "AutoUpdateMaps.xml";

        #region 配置器配置属性

        /// <summary>
        /// 更新文件目录
        /// </summary>
        public static string FilesRootPath
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "FilesRootPath", true);
                if (string.IsNullOrEmpty(rtn))
                {
                    rtn = System.AppDomain.CurrentDomain.BaseDirectory;
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "FilesRootPath", rtn, true);
                }
                return TrailingPath(rtn);
            }
            set
            {
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "FilesRootPath", value, true);
            }
        }

        #endregion

        #region 启动器配置属性
        /// <summary>
        /// 启动器配置文件名
        /// </summary>
        public static string UpdateIniFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AutoUpdate.ini");
        /// <summary>
        /// 初始化标记
        /// </summary>
        public static bool InitLocked
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "InitLocked", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "InitLocked", "0", true, Common.UpdateIniFile);
                    return false;
                }
                return rtn == "1";
            }
            set
            {
                var str = value ? "1" : "0";
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "InitLocked", str, true, Common.UpdateIniFile);
            }
        }
        /// <summary>
        /// 使用简化窗体
        /// </summary>
        public static bool UseFormLite
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "UseFormLite", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "UseFormLite", "0", true, Common.UpdateIniFile);
                    return false;
                }
                return rtn == "1";
            }
            set
            {
                var str = value ? "1" : "0";
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "UseFormLite", str, true, Common.UpdateIniFile);
            }
        }
        /// <summary>
        /// 配置文件地址
        /// </summary>
        public static string ConfigUrl
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "ConfigUrl", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    rtn = "http://";
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "ConfigUrl", rtn, true, Common.UpdateIniFile);
                }
                return rtn;
            }
            set
            {
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "ConfigUrl", value, true, Common.UpdateIniFile);
            }
        }

        /// <summary>
        /// 主程序版本
        /// </summary>
        public static string AppVersion
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "AppVersion", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    rtn = "";
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppVersion", rtn, true, Common.UpdateIniFile);
                }
                return rtn;
            }
            set
            {
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppVersion", value, true, Common.UpdateIniFile);
            }
        }
        /// <summary>
        /// 主程序更新目录
        /// </summary>
        public static string AppRootPath
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "AppRootPath", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    rtn = System.AppDomain.CurrentDomain.BaseDirectory;
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppRootPath", rtn, true, Common.UpdateIniFile);
                }
                return TrailingPath(rtn);
            }
            set
            {
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppRootPath", value, true, Common.UpdateIniFile);
            }
        }
        /// <summary>
        /// 主程序更新缓存目录
        /// </summary>
        public static string AppRootTmp
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "AppRootTmp", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    rtn = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "uptemp");
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppRootTmp", rtn, true, Common.UpdateIniFile);
                }
                return TrailingPath(rtn);
            }
            set
            {
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppRootTmp", value, true, Common.UpdateIniFile);
            }
        }
        /// <summary>
        /// 启动器绝对路径
        /// </summary>
        public static string AppLaunchExe
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "AppLaunchExe", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    rtn = "";
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppLaunchExe", rtn, true);
                }
                return rtn;
            }
            set
            {
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppLaunchExe", value, true, Common.UpdateIniFile);
            }
        }
        /// <summary>
        /// 启动自动更新
        /// </summary>
        public static bool AutoUpdate
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "AutoUpdate", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AutoUpdate", "0", true, Common.UpdateIniFile);
                    return false;
                }
                return rtn == "1";
            }
            set
            {
                var str = value ? "1" : "0";
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AutoUpdate", str, true, Common.UpdateIniFile);
            }
        }
        /// <summary>
        /// 自启动主程序
        /// </summary>
        public static bool AppRestart
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "AppRestart", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppRestart", "0", true, Common.UpdateIniFile);
                    return false;
                }
                return rtn == "1";
            }
            set
            {
                var str = value ? "1" : "0";
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AppRestart", str, true, Common.UpdateIniFile);
            }
        }
        /// <summary>
        /// 自动关闭更新程序
        /// </summary>
        public static bool AutoClose
        {
            get
            {
                var rtn = ConfHelper.ReadValue(ConfHelper.SECTION_SETTINGS, "AutoClose", true, Common.UpdateIniFile);
                if (string.IsNullOrEmpty(rtn))
                {
                    //ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AutoClose", "0", true, Common.UpdateIniFile);
                    return false;
                }
                return rtn == "1";
            }
            set
            {
                var str = value ? "1" : "0";
                ConfHelper.WriteValue(ConfHelper.SECTION_SETTINGS, "AutoClose", str, true, Common.UpdateIniFile);
            }
        }
        #endregion

        #region 通用处理函数
        /// <summary>
        /// 文件绝对路径补全
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string TrailingFilePath(string path)
        {
            var flag = !String.IsNullOrWhiteSpace(path) && path.IndexOfAny(System.IO.Path.GetInvalidPathChars().ToArray()) == -1 && Path.IsPathRooted(path) && !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal);
            return flag ? path : TrailingPath(AppDomain.CurrentDomain.BaseDirectory) + path;
        }
        
        /// <summary>
        /// 绝对路径补全
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string TrailingPath(string path)
        {
            if (string.IsNullOrEmpty(path)) return path;
            return Path.GetFullPath(path).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
        }

        /// <summary>
        /// 判断是否http地址
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsHttpAddress(string input)
        {
            if (string.IsNullOrWhiteSpace(input)) return false;
            return System.Text.RegularExpressions.Regex.IsMatch(input, @"^(http(s)?://)?(localhost|[\d.]+|\w+(\.\w+)*)(:\d+)?(/[\w-./?%&=]*)?$");
        }
        /// <summary>
        /// 判断是否IP地址
        /// </summary>
        /// <param name="input">待判断的IP地址</param>
        /// <returns></returns>
        public static bool IsIPAddress(string input)
        {
            if (string.IsNullOrWhiteSpace(input)) return false;
            return System.Text.RegularExpressions.Regex.IsMatch(input, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }
        /// <summary>
        /// 获取指令
        /// </summary>
        /// <param name="args"></param>
        /// <param name="cmd"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static bool TryGetCommand(string[] args, string cmd, out bool t)
        {
            t = false;
            if (args != null)
            {
                for (int i = 0; i < args.Length; i++)
                {
                    if (!string.IsNullOrEmpty(args[i]))
                    {
                        if (args[i].StartsWith(cmd) && args[i].IndexOf('=') > -1)
                        {
                            return Boolean.TryParse(args[i].Substring(args[i].IndexOf('=') + 1), out t);
                        }
                        else if (args[i].StartsWith(cmd))
                        {
                            t = true;
                            return true;
                        }
                    }

                }
            }
            return false;
        }
        /// <summary>
        /// 获取指令
        /// </summary>
        /// <param name="args"></param>
        /// <param name="cmd"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static bool TryGetCommand(string[] args, string cmd, out string t)
        {
            t = string.Empty;
            if (args != null)
            {
                for (int i = 0; i < args.Length; i++)
                {

                    if (!string.IsNullOrEmpty(args[i]))
                    {
                        if (args[i].StartsWith(cmd) && args[i].IndexOf('=') > -1)
                        {
                            t = args[i].Substring(args[i].IndexOf('=') + 1);
                            return true;
                        }
                        else if (args[i].StartsWith(cmd))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        #endregion

        #region 进程操作函数
        /// <summary>
        /// 进程是否正在运行
        /// </summary>
        /// <param name="launchPath"></param>
        /// <returns></returns>
        public static bool IsProcessRunning(string launchPath)
        {
            string processName = System.IO.Path.GetFileNameWithoutExtension(launchPath);
            Process[] processes = Process.GetProcessesByName(processName);

            foreach (Process process in processes)
            {
                if (process.MainModule.FileName.Equals(launchPath, StringComparison.OrdinalIgnoreCase))
                {
                    Console.WriteLine("IsRunning:" + processName);
                    return true;
                }
            }

            return false;
        }
        /// <summary>
        /// 获取与当前进程相同的正在运行的实例，没有运行的实例返回null;
        /// </summary>
        public static Process ProcessInstance()
        {
            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);

            foreach (Process process in processes)
            {
                if (process.Id != current.Id)
                {
                    if (process.MainModule.FileName == current.MainModule.FileName)
                    {
                        return process;
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// 结束指定路径程序
        /// </summary>
        /// <param name="launchPath"></param>
        /// <exception cref="Exception"></exception>
        public static bool CloseProcess(string launchPath)
        {
            Process[] processes = Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(launchPath));

            foreach (Process process in processes)
            {
                try
                {
                    if (!process.HasExited)
                    {
                        process.CloseMainWindow(); // 尝试关闭主窗口
                        process.WaitForExit(5000); // 等待程序退出，最多等待5秒钟
                    }

                    if (!process.HasExited)
                    {
                        process.Kill(); // 如果程序仍未退出，强制终止进程
                        process.WaitForExit(5000); // 等待程序退出，最多等待5秒钟
                    }
                }
                catch (Exception ex)
                {
                    //return false;
                    throw new Exception("关闭外部程序时发生错误：" + ex.Message);
                }
            }
            return true;
        }
        /// <summary>
        /// 运行指定路径程序
        /// </summary>
        /// <param name="name"></param>
        public static bool StartProcess(string launchPath)
        {
            try
            {
                if (string.IsNullOrEmpty(launchPath)) return false;
                System.Diagnostics.ProcessStartInfo process = new System.Diagnostics.ProcessStartInfo();
                process.FileName = launchPath;
                System.Diagnostics.Process prc;
                prc = System.Diagnostics.Process.Start(process);
            }
            catch (Exception ex)
            {
                //return false;
                throw new Exception("运行外部程序时发生错误：" + ex.Message);
            }
            return true;
        }


        /// <summary>
        /// 该函数设置由不同线程产生的窗口的显示状态。
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <param name="cmdShow">指定窗口如何显示。查看允许值列表，请查阅ShowWlndow函数的说明部分。</param>
        /// <returns>如果函数原来可见，返回值为非零；如果函数原来被隐藏，返回值为零。</returns>
        [DllImport("User32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
        /// <summary>
        /// 该函数将创建指定窗口的线程设置到前台，并且激活该窗口。键盘输入转向该窗口，并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。
        /// </summary>
        /// <param name="hWnd">将被激活并被调入前台的窗口句柄。</param>
        /// <returns>如果窗口设入了前台，返回值为非零；如果窗口未被设入前台，返回值为零。</returns>
        [DllImport("User32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        /// <summary>
        /// 显示已运行的程序。
        /// </summary>
        public static void HandleRunningInstance(Process instance)
        {
            ShowWindowAsync(instance.MainWindowHandle, 1); //显示
            SetForegroundWindow(instance.MainWindowHandle); //放到前端
        }
        #endregion

        #region 核心操作函数

        /// <summary>
        /// 清单文件链接补全
        /// </summary>
        /// <param name="url">文件父目录</param>
        /// <returns></returns>
        public static string FormatManifestUrl(string url)
        {
            var configurl = Common.ConfigUrl;
            if (IsHttpAddress(url))
            {
                if (url.ToLower().LastIndexOf(".xml") > 0)
                    configurl = url;
                else
                    configurl = url + "/" + Common.ManifestName;
            }
            return new Uri(configurl).ToString();
        }

        /// <summary>
        /// 选择文件或文件夹文件，返回文件绝对路径
        /// </summary>
        /// <returns></returns>
        public static string[] SelectFolderOrFiles()
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.ValidateNames = false;
            openFileDialog.CheckFileExists = false;
            openFileDialog.CheckPathExists = true;
            openFileDialog.Multiselect = true;
            openFileDialog.FileName = "Folder";

            List<string> results = new List<string>();
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                foreach (string path in openFileDialog.FileNames)
                {
                    string selectedPath = Path.GetDirectoryName(path);
                    string[] tmpArrs = null;
                    if (File.Exists(path))
                    {
                        // 如果选中的是文件，则返回文件的绝对路径
                        tmpArrs = new string[] { path };
                    }
                    else if (Directory.Exists(selectedPath))
                    {
                        // 如果选中的是文件夹，则遍历文件夹中的所有文件，并返回它们的绝对路径
                        tmpArrs = Directory.GetFiles(selectedPath, "*", SearchOption.AllDirectories);
                    }
                    if (tmpArrs != null) results.AddRange(tmpArrs);
                }

                return results.ToArray();
            }
            return null;
        }

        /// <summary>
        /// 获得所有文件路径的主目录，文件/文件夹路径必须为相同根目录
        /// </summary>
        /// <param name="filePaths"></param>
        /// <param name="rootPath"></param>
        /// <returns></returns>
        public static string GetCommonBaseDirectory(IEnumerable<string> filePaths)
        {
            string GetCommonParentDir(IEnumerable<string> paths)
            {
                string commonParent = Path.GetFullPath(paths.FirstOrDefault());

                foreach (string path in paths)
                {
                    commonParent = GetCommonParent(commonParent, Path.GetFullPath(path));
                }

                return commonParent;
            }

            string GetCommonParent(string path1, string path2)
            {
                while (path1 != null && !path1.Equals(path2, StringComparison.OrdinalIgnoreCase))
                {
                    if (path2 != null && path1.Length < path2.Length)
                    {
                        path2 = Path.GetDirectoryName(path2);
                    }
                    else
                    {
                        path1 = Path.GetDirectoryName(path1);
                    }
                }

                return path1;
            }
            return GetCommonParentDir(filePaths);
        }
        /// <summary>
        /// 获得所有文件路径的主目录，文件/文件夹路径必须为相同根目录
        /// </summary>
        /// <param name="filePaths"></param>
        /// <param name="rootPath"></param>
        /// <returns></returns>
        public static string GetCommonParentDirectory(string[] filePaths, string rootPath)
        {
            var rootPath1 = Directory.GetDirectoryRoot(Common.GetCommonBaseDirectory(filePaths));
            var rootPath2 = string.IsNullOrWhiteSpace(rootPath) ? null : Directory.GetDirectoryRoot(TrailingPath(rootPath));
            
            List<string> tmpPaths = new List<string>();
            tmpPaths.AddRange(filePaths);
            if (!string.IsNullOrWhiteSpace(rootPath2) && rootPath2.Equals(rootPath1, StringComparison.OrdinalIgnoreCase))
                tmpPaths.Add(rootPath);
            return Common.GetCommonBaseDirectory(tmpPaths.ToArray());
        }
        /// <summary>
        /// 判断清单缓存列表文件是否有改动，根据hash值判断
        /// </summary>
        /// <param name="modelData"></param>
        /// <returns></returns>
        public static bool CheckChangeFiles(UptBaseModel modelData)
        {
            if (modelData != null && modelData.files != null && modelData.files.Count > 0)
            {
                foreach (var item in modelData.files)
                {
                    Console.WriteLine(item.filePath);

                    if (File.Exists(item.filePath))
                    {
                        var nowHash1 = EncryptParse.GetFileMD5Hash(item.filePath);
                        if (item.hash1 != nowHash1)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 清单文件 读取并解析XML到对象（C#客户端解析XML可参照此处）
        /// </summary>
        /// <param name="filePath"></param>
        public static UptBaseModel ReadAutoUpdateMapsXml(string filePath)
        {
            UptBaseModel modelData = new UptBaseModel() {
                version = "1.0.0.0",
                description = "",
                files = new List<FileInfoModel>(),
            };

            if (!File.Exists(filePath)) return modelData;

            var targetXml = FileOperate.ReadText(filePath);
            if (string.IsNullOrEmpty(targetXml)) return modelData;

            var tempModel = XmlHelper.Deserialize<UptBaseModel>(targetXml);
            if (tempModel != null)
            {
                modelData.version = tempModel.version;
                modelData.description = tempModel.description;
                modelData.server = EncryptParse.DESDecrypt(tempModel.server ?? "", EncryptParse.GenerateDESKey(tempModel.version ?? ""));
                if (tempModel.files != null && tempModel.files.Count > 0)
                {
                    modelData.count = tempModel.files.Count;
                    foreach (var item in tempModel.files)
                    {
                        //DES解密信息
                        item.fileName = EncryptParse.DESDecrypt(item.fileName, EncryptParse.GenerateDESKey(item.hash1));
                        item.filePath = EncryptParse.DESDecrypt(item.filePath, EncryptParse.GenerateDESKey(item.hash1));
                        item.fileDrect = EncryptParse.DESDecrypt(item.fileDrect, EncryptParse.GenerateDESKey(item.hash1));
                        item.urlDrect = EncryptParse.DESDecrypt(item.urlDrect ?? "", EncryptParse.GenerateDESKey(item.hash1));
                    }

                    modelData.files.Clear();
                    modelData.files.AddRange(tempModel.files);
                }
            }
            return modelData;
        }

        /// <summary>
        /// 清单文件 加密并保存内容到XML
        /// </summary>
        /// <param name="modelData"></param>
        /// <param name="toPath"></param>
        public static void SaveAutoUpdateMapsXml(UptBaseModel modelData, string toPath)
        {
            var tempModel = new UptBaseModel();
            tempModel.version = modelData.version;
            tempModel.description = modelData.description;
            tempModel.server = EncryptParse.DESEncrypt(modelData.server ?? "", EncryptParse.GenerateDESKey(modelData.version ?? ""));
            if (modelData.files != null && modelData.files.Count > 0)
            {
                foreach (var item in modelData.files)
                {
                    var info = new FileInfoModel();
                    info.hash1 = item.hash1;
                    info.fileVer = item.fileVer;
                    info.fileBytes = item.fileBytes;
                    info.lastWTime = item.lastWTime;
                    info.fileName = EncryptParse.DESEncrypt(item.fileName ?? "", EncryptParse.GenerateDESKey(item.hash1));
                    info.filePath = EncryptParse.DESEncrypt(item.filePath ?? "", EncryptParse.GenerateDESKey(item.hash1));
                    info.fileDrect = EncryptParse.DESEncrypt(item.fileDrect ?? "", EncryptParse.GenerateDESKey(item.hash1));
                    info.urlDrect = EncryptParse.DESEncrypt(item.urlDrect ?? "", EncryptParse.GenerateDESKey(item.hash1));
                    tempModel.files.Add(info);
                }
                tempModel.count = tempModel.files.Count;
            }
            FileOperate.WriteText(TrailingFilePath(toPath), XmlHelper.Serialize(tempModel, true, true));
        }
        /// <summary>
        /// 重载清单文件信息缓存对象
        /// </summary>
        /// <param name="modelData"></param>
        public static void ReloadAutoUpdateMaps(UptBaseModel modelData, string rootPath)
        {
            foreach (var item in modelData.files.ToArray())
            {
                Common.ReflashOrAddFileModel(modelData, item.filePath, rootPath);
            }
        }
        /// <summary>
        /// 读取更新，更新清单文件信息缓存对象中的清单文件
        /// </summary>
        /// <param name="modelData"></param>
        /// <param name="filePath"></param>
        public static void ReflashOrAddFileModel(UptBaseModel modelData, string filePath, string rootPath)
        {
            //var tempModels = modelData.files.Where(x => x.filePath == filePath).ToList();
            if (filePath.IndexOf(rootPath) == -1)
            {
                throw new Exception("文件 " + filePath + " \r\n 需存放在更新清单配置文件当前所在目录或子目录下");
            }

            var tempModels = new List<FileInfoModel>();
            foreach (var item in modelData.files)
            {
                //判断是否已存在该文件路径
                if (item.filePath == filePath) tempModels.Add(item);
            }

            if (tempModels.Count > 0) //更新文件信息 
            {
                foreach (var item in tempModels)
                {
                    modelData.files.Remove(item);
                    modelData.files.Add(GetFileModel(filePath, modelData.server));
                }
            }
            else //添加新文件
            {
                modelData.files.Add(GetFileModel(filePath, modelData.server));
            }
        }

        /// <summary>
        /// 移除文件，从清单文件信息缓存对象中根据hash1移除文件
        /// </summary>
        /// <param name="modelData"></param>
        /// <param name="hash1"></param>
        public static void RemoveFileModel(UptBaseModel modelData, string hash1)
        {
            //从缓存中移除
            //FileInfoModel mtemp = modelData.files.Where(x => x.hash1 == hash1).FirstOrDefault();
            FileInfoModel mtemp = null;
            foreach (var item in modelData.files)
            {
                if (item.hash1 == hash1) mtemp = item;
            }

            if (mtemp != null)
                modelData.files.Remove(mtemp);
        }

        /// <summary>
        /// 读取，获取文件信息返回清单缓存对象 FileModel
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="urlRoot"></param>
        /// <returns></returns>
        private static FileInfoModel GetFileModel(string filePath, string urlRoot)
        {
            FileInfoModel fileModel = new FileInfoModel();
            //再次更新及信息
            FileInfo fileInfo = new FileInfo(filePath);
            FileVersionInfo fileVer = FileVersionInfo.GetVersionInfo(fileInfo.FullName);
            fileModel.hash1 = EncryptParse.GetFileMD5Hash(filePath); //获取当前文件的HASH值
            fileModel.fileName = fileInfo.Name;
            fileModel.filePath = fileInfo.FullName;
            fileModel.fileDrect = fileInfo.FullName.Replace(Common.FilesRootPath, "");
            fileModel.urlDrect = new Uri(urlRoot.TrimEnd('\\').TrimEnd('/') + "/" + fileModel.fileDrect).AbsoluteUri;
            fileModel.fileBytes = fileInfo.Length;
            fileModel.lastWTime = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
            fileModel.fileVer = String.Format("{0}.{1}.{2}.{3}", fileVer.FileMajorPart, fileVer.FileMinorPart, fileVer.FileBuildPart, fileVer.FilePrivatePart);
            fileVer = null;
            fileInfo = null;
            return fileModel;
        }
        #endregion
    }
}
